#ifndef _OBJECT_POOL_H_
#define _OBJECT_POOL_H_

#include <vector>

namespace serika
{
	namespace ut
	{
		template<class _Type, size_t _Size = 100, size_t _Inc = 50>
		class ObjectPool
		{
		public:
			ObjectPool(void);
			~ObjectPool(void);

		private:
			std::vector<_Type*> freeList;
			size_t poolSize;

		public:
			_Type* Alloc();
			void Free(_Type* o);

		private:
			void Increase(int c);
		};

		template<class _Type, size_t _Size, size_t _Inc>
		ObjectPool<_Type, _Size, _Inc>::ObjectPool()
		{
			this->poolSize = 0;
			this->Increase(_Size);
		}

		template<class _Type, size_t _Size, size_t _Inc>
		ObjectPool<_Type, _Size, _Inc>::~ObjectPool()
		{
			for (typename std::vector<_Type*>::iterator itr = this->freeList.begin(); itr != this->freeList.end(); ++itr)
			{
				delete (*itr);
			}
			this->freeList.clear();
		}

		template<class _Type, size_t _Size, size_t _Inc>
		_Type* ObjectPool<_Type, _Size, _Inc>::Alloc()
		{
			_Type* r = NULL;
			if (this->freeList.empty())
			{
				Increase(_Inc);
			}
			r = this->freeList.back();
			this->freeList.pop_back();
			return r;
		}

		template<class _Type, size_t _Size, size_t _Inc>
		void ObjectPool<_Type, _Size, _Inc>::Free(_Type* o)
		{
			this->freeList.push_back(o);
		}

		template<class _Type, size_t _Size, size_t _Inc>
		void ObjectPool<_Type, _Size, _Inc>::Increase(int c)
		{
			this->poolSize += c;
			this->freeList.reserve(this->poolSize);

			for (int i = 0; i < c; i++)
			{
				this->freeList.push_back(new _Type);
			}
		}

	}

}
#endif
